// deque standard header
#pragma once
#ifndef _DEQUE_
#define _DEQUE_
#ifndef RC_INVOKED
#include <xmemory>

#if _HAS_CXX17
#include <xpolymorphic_allocator.h>
#endif // _HAS_CXX17

#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new

_STD_BEGIN
// DEQUE PARAMETERS
#define _DEQUEMAPSIZ 8 // minimum map size, at least 1
#define _DEQUESIZ                               \
    (sizeof(value_type) <= 1                    \
            ? 16                                \
            : sizeof(value_type) <= 2           \
                  ? 8                           \
                  : sizeof(value_type) <= 4 ? 4 \
                                            : sizeof(value_type) <= 8 ? 2 : 1) // elements per block (a power of 2)

// CLASS TEMPLATE _Deque_unchecked_const_iterator
template <class _Mydeque>
class _Deque_unchecked_const_iterator { // iterator for nonmutable deque
private:
    using _Size_type = typename _Mydeque::size_type;

public:
    using iterator_category = random_access_iterator_tag;

    using value_type      = typename _Mydeque::value_type;
    using difference_type = typename _Mydeque::difference_type;
    using pointer         = typename _Mydeque::const_pointer;
    using reference       = const value_type&;

    _Deque_unchecked_const_iterator() : _Mycont(), _Myoff(0) { // construct with null pointer
    }

    _Deque_unchecked_const_iterator(_Size_type _Off, const _Container_base12* _Pdeque)
        : _Mycont(static_cast<const _Mydeque*>(_Pdeque)), _Myoff(_Off) { // construct with offset _Off
    }

    _NODISCARD reference operator*() const { // return designated object
        _Size_type _Block = _Mycont->_Getblock(_Myoff);
        _Size_type _Off   = _Myoff % _DEQUESIZ;
        return _Mycont->_Map[_Block][_Off];
    }

    _NODISCARD pointer operator->() const { // return pointer to class object
        return pointer_traits<pointer>::pointer_to(**this);
    }

    _Deque_unchecked_const_iterator& operator++() { // preincrement
        ++_Myoff;
        return *this;
    }

    _Deque_unchecked_const_iterator operator++(int) { // postincrement
        _Deque_unchecked_const_iterator _Tmp = *this;
        ++*this;
        return _Tmp;
    }

    _Deque_unchecked_const_iterator& operator--() { // predecrement
        --_Myoff;
        return *this;
    }

    _Deque_unchecked_const_iterator operator--(int) { // postdecrement
        _Deque_unchecked_const_iterator _Tmp = *this;
        --*this;
        return _Tmp;
    }

    _Deque_unchecked_const_iterator& operator+=(const difference_type _Off) { // increment by integer
        _Myoff += _Off;
        return *this;
    }

    _NODISCARD _Deque_unchecked_const_iterator operator+(const difference_type _Off) const { // return this + integer
        _Deque_unchecked_const_iterator _Tmp = *this;
        return _Tmp += _Off;
    }

    _Deque_unchecked_const_iterator& operator-=(const difference_type _Off) { // decrement by integer
        return *this += -_Off;
    }

    _NODISCARD _Deque_unchecked_const_iterator operator-(const difference_type _Off) const { // return this - integer
        _Deque_unchecked_const_iterator _Tmp = *this;
        return _Tmp -= _Off;
    }

    _NODISCARD difference_type operator-(
        const _Deque_unchecked_const_iterator& _Right) const { // return difference of iterators
        return static_cast<difference_type>(_Myoff - _Right._Myoff);
    }

    _NODISCARD reference operator[](const difference_type _Off) const { // subscript
        return *(*this + _Off);
    }

    _NODISCARD bool operator==(const _Deque_unchecked_const_iterator& _Right) const { // test for iterator equality
        return _Myoff == _Right._Myoff;
    }

    _NODISCARD bool operator!=(const _Deque_unchecked_const_iterator& _Right) const { // test for iterator inequality
        return !(*this == _Right);
    }

    _NODISCARD bool operator<(const _Deque_unchecked_const_iterator& _Right) const { // test if this < _Right
        return _Myoff < _Right._Myoff;
    }

    _NODISCARD bool operator>(const _Deque_unchecked_const_iterator& _Right) const { // test if this > _Right
        return _Right < *this;
    }

    _NODISCARD bool operator<=(const _Deque_unchecked_const_iterator& _Right) const { // test if this <= _Right
        return !(_Right < *this);
    }

    _NODISCARD bool operator>=(const _Deque_unchecked_const_iterator& _Right) const { // test if this >= _Right
        return !(*this < _Right);
    }

    const _Container_base12* _Getcont() const { // get container pointer
        return _Mycont;
    }

    const _Mydeque* _Mycont; // pointer to deque
    _Size_type _Myoff; // offset of element in deque
};

template <class _Mydeque>
_NODISCARD inline _Deque_unchecked_const_iterator<_Mydeque> operator+(
    typename _Deque_unchecked_const_iterator<_Mydeque>::difference_type _Off,
    _Deque_unchecked_const_iterator<_Mydeque> _Next) { // add offset to iterator
    return _Next += _Off;
}

// CLASS TEMPLATE _Deque_unchecked_iterator
template <class _Mydeque>
class _Deque_unchecked_iterator : public _Deque_unchecked_const_iterator<_Mydeque> { // iterator for mutable deque
private:
    using _Size_type = typename _Mydeque::size_type;
    using _Mybase    = _Deque_unchecked_const_iterator<_Mydeque>;

public:
    using iterator_category = random_access_iterator_tag;

    using value_type      = typename _Mydeque::value_type;
    using difference_type = typename _Mydeque::difference_type;
    using pointer         = typename _Mydeque::pointer;
    using reference       = value_type&;

    _Deque_unchecked_iterator() { // construct with null pointer
    }

    _Deque_unchecked_iterator(_Size_type _Off, const _Container_base12* _Pdeque)
        : _Mybase(_Off, _Pdeque) { // construct with offset _Off
    }

    _NODISCARD reference operator*() const { // return designated object
        return (reference) * *(_Mybase*) this;
    }

    _NODISCARD pointer operator->() const { // return pointer to class object
        return pointer_traits<pointer>::pointer_to(**this);
    }

    _Deque_unchecked_iterator& operator++() { // preincrement
        ++*(_Mybase*) this;
        return *this;
    }

    _Deque_unchecked_iterator operator++(int) { // postincrement
        _Deque_unchecked_iterator _Tmp = *this;
        ++*this;
        return _Tmp;
    }

    _Deque_unchecked_iterator& operator--() { // predecrement
        --*(_Mybase*) this;
        return *this;
    }

    _Deque_unchecked_iterator operator--(int) { // postdecrement
        _Deque_unchecked_iterator _Tmp = *this;
        --*this;
        return _Tmp;
    }

    _Deque_unchecked_iterator& operator+=(const difference_type _Off) { // increment by integer
        *(_Mybase*) this += _Off;
        return *this;
    }

    _NODISCARD _Deque_unchecked_iterator operator+(const difference_type _Off) const { // return this + integer
        _Deque_unchecked_iterator _Tmp = *this;
        return _Tmp += _Off;
    }

    _Deque_unchecked_iterator& operator-=(const difference_type _Off) { // decrement by integer
        return *this += -_Off;
    }

    _NODISCARD _Deque_unchecked_iterator operator-(const difference_type _Off) const { // return this - integer
        _Deque_unchecked_iterator _Tmp = *this;
        return _Tmp -= _Off;
    }

    _NODISCARD difference_type operator-(const _Mybase& _Right) const { // return difference of iterators
        return *(_Mybase*) this - _Right;
    }

    _NODISCARD reference operator[](const difference_type _Off) const { // subscript
        return *(*this + _Off);
    }
};

template <class _Mydeque>
_NODISCARD inline _Deque_unchecked_iterator<_Mydeque> operator+(
    typename _Deque_unchecked_iterator<_Mydeque>::difference_type _Off,
    _Deque_unchecked_iterator<_Mydeque> _Next) { // add offset to iterator
    return _Next += _Off;
}

// CLASS TEMPLATE _Deque_const_iterator
template <class _Mydeque>
class _Deque_const_iterator : public _Iterator_base12 { // iterator for nonmutable deque
private:
    using _Size_type = typename _Mydeque::size_type;

public:
    using iterator_category = random_access_iterator_tag;

    using value_type      = typename _Mydeque::value_type;
    using difference_type = typename _Mydeque::difference_type;
    using pointer         = typename _Mydeque::const_pointer;
    using reference       = const value_type&;

    using _Mydeque_t = _Mydeque; // helper for expression evaluator
    enum { _EEN_DS = _DEQUESIZ }; // helper for expression evaluator
    _Deque_const_iterator() : _Myoff(0) { // construct with null pointer
        _Setcont(nullptr);
    }

    _Deque_const_iterator(_Size_type _Off, const _Container_base12* _Pdeque)
        : _Myoff(_Off) { // construct with offset _Off in *_Pdeque
        _Setcont((_Mydeque*) _Pdeque);
    }

    _NODISCARD reference operator*() const { // return designated object
        const auto _Mycont = static_cast<const _Mydeque*>(this->_Getcont());
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Mycont, "cannot dereference value-initialized deque iterator");
        _STL_VERIFY(_Mycont->_Myoff <= this->_Myoff && this->_Myoff < _Mycont->_Myoff + _Mycont->_Mysize,
            "cannot deference out of range deque iterator");
#endif // _ITERATOR_DEBUG_LEVEL != 0

        _Size_type _Block = _Mycont->_Getblock(_Myoff);
        _Size_type _Off   = _Myoff % _DEQUESIZ;
        return _Mycont->_Map[_Block][_Off];
    }

    _NODISCARD pointer operator->() const { // return pointer to class object
        return pointer_traits<pointer>::pointer_to(**this);
    }

    _Deque_const_iterator& operator++() { // preincrement
#if _ITERATOR_DEBUG_LEVEL != 0
        const auto _Mycont = static_cast<const _Mydeque*>(this->_Getcont());
        _STL_VERIFY(_Mycont, "cannot increment value-initialized deque iterator");
        _STL_VERIFY(this->_Myoff < _Mycont->_Myoff + _Mycont->_Mysize, "cannot increment deque iterator past end");
#endif // _ITERATOR_DEBUG_LEVEL != 0

        ++_Myoff;
        return *this;
    }

    _Deque_const_iterator operator++(int) { // postincrement
        _Deque_const_iterator _Tmp = *this;
        ++*this;
        return _Tmp;
    }

    _Deque_const_iterator& operator--() { // predecrement
#if _ITERATOR_DEBUG_LEVEL != 0
        const auto _Mycont = static_cast<const _Mydeque*>(this->_Getcont());
        _STL_VERIFY(_Mycont, "cannot decrement value-initialized deque iterator");
        _STL_VERIFY(_Mycont->_Myoff < this->_Myoff, "cannot decrement deque iterator before begin");
#endif // _ITERATOR_DEBUG_LEVEL != 0

        --_Myoff;
        return *this;
    }

    _Deque_const_iterator operator--(int) { // postdecrement
        _Deque_const_iterator _Tmp = *this;
        --*this;
        return _Tmp;
    }

    _Deque_const_iterator& operator+=(const difference_type _Off) { // increment by integer
#if _ITERATOR_DEBUG_LEVEL != 0
        if (_Off != 0) {
            const auto _Mycont = static_cast<const _Mydeque*>(this->_Getcont());
            _STL_VERIFY(_Mycont, "cannot seek value-initialized deque iterator");
            _STL_VERIFY(
                _Mycont->_Myoff <= this->_Myoff + _Off && this->_Myoff + _Off <= _Mycont->_Myoff + _Mycont->_Mysize,
                "cannot seek deque iterator out of range");
        }
#endif // _ITERATOR_DEBUG_LEVEL != 0

        _Myoff += _Off;
        return *this;
    }

    _NODISCARD _Deque_const_iterator operator+(const difference_type _Off) const { // return this + integer
        _Deque_const_iterator _Tmp = *this;
        return _Tmp += _Off;
    }

    _Deque_const_iterator& operator-=(const difference_type _Off) { // decrement by integer
        return *this += -_Off;
    }

    _NODISCARD _Deque_const_iterator operator-(const difference_type _Off) const { // return this - integer
        _Deque_const_iterator _Tmp = *this;
        return _Tmp -= _Off;
    }

    _NODISCARD difference_type operator-(const _Deque_const_iterator& _Right) const { // return difference of iterators
        _Compat(_Right);
        return static_cast<difference_type>(this->_Myoff - _Right._Myoff);
    }

    _NODISCARD reference operator[](const difference_type _Off) const { // subscript
        return *(*this + _Off);
    }

    _NODISCARD bool operator==(const _Deque_const_iterator& _Right) const { // test for iterator equality
        _Compat(_Right);
        return this->_Myoff == _Right._Myoff;
    }

    _NODISCARD bool operator!=(const _Deque_const_iterator& _Right) const { // test for iterator inequality
        return !(*this == _Right);
    }

    _NODISCARD bool operator<(const _Deque_const_iterator& _Right) const { // test if this < _Right
        _Compat(_Right);
        return this->_Myoff < _Right._Myoff;
    }

    _NODISCARD bool operator>(const _Deque_const_iterator& _Right) const { // test if this > _Right
        return _Right < *this;
    }

    _NODISCARD bool operator<=(const _Deque_const_iterator& _Right) const { // test if this <= _Right
        return !(_Right < *this);
    }

    _NODISCARD bool operator>=(const _Deque_const_iterator& _Right) const { // test if this >= _Right
        return !(*this < _Right);
    }

    void _Compat(const _Deque_const_iterator& _Right) const { // test for compatible iterator pair
#if _ITERATOR_DEBUG_LEVEL == 0
        (void) _Right;
#else // _ITERATOR_DEBUG_LEVEL == 0
        _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "deque iterators incompatible");
#endif // _ITERATOR_DEBUG_LEVEL == 0
    }

    void _Setcont(const _Mydeque* _Pdeque) { // set container pointer
        this->_Adopt(_Pdeque);
    }

    using _Prevent_inheriting_unwrap = _Deque_const_iterator;

    _NODISCARD _Deque_unchecked_const_iterator<_Mydeque> _Unwrapped() const {
        return {this->_Myoff, this->_Getcont()};
    }

    void _Verify_offset(const difference_type _Off) const noexcept {
#if _ITERATOR_DEBUG_LEVEL == 0
        (void) _Off;
#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ // vvv _ITERATOR_DEBUG_LEVEL != 0 vvv
        if (_Off != 0) {
            const auto _Mycont = static_cast<const _Mydeque*>(this->_Getcont());
            _STL_VERIFY(_Mycont, "cannot use value-initialized deque iterator");
            _STL_VERIFY(
                _Mycont->_Myoff <= this->_Myoff + _Off && this->_Myoff + _Off <= _Mycont->_Myoff + _Mycont->_Mysize,
                "cannot seek deque iterator out of range");
        }
#endif // _ITERATOR_DEBUG_LEVEL == 0
    }

#if _ITERATOR_DEBUG_LEVEL != 0
    friend void _Verify_range(const _Deque_const_iterator& _First, const _Deque_const_iterator& _Last) {
        // note _Compat check inside operator<=
        _STL_VERIFY(_First <= _Last, "deque iterators transposed");
    }
#endif // _ITERATOR_DEBUG_LEVEL != 0

    void _Seek_to(const _Deque_unchecked_const_iterator<_Mydeque>& _UIt) {
        _Myoff = _UIt._Myoff;
    }

    _Size_type _Myoff; // offset of element in deque
};

template <class _Mydeque>
_NODISCARD inline _Deque_const_iterator<_Mydeque> operator+(
    typename _Deque_const_iterator<_Mydeque>::difference_type _Off,
    _Deque_const_iterator<_Mydeque> _Next) { // add offset to iterator
    return _Next += _Off;
}

// CLASS TEMPLATE _Deque_iterator
template <class _Mydeque>
class _Deque_iterator : public _Deque_const_iterator<_Mydeque> { // iterator for mutable deque
private:
    using _Size_type = typename _Mydeque::size_type;
    using _Mybase    = _Deque_const_iterator<_Mydeque>;

public:
    using _Deque_unchecked_type = _Deque_unchecked_iterator<_Mydeque>;
    using iterator_category     = random_access_iterator_tag;

    using value_type      = typename _Mydeque::value_type;
    using difference_type = typename _Mydeque::difference_type;
    using pointer         = typename _Mydeque::pointer;
    using reference       = value_type&;

    _Deque_iterator() { // construct with null deque pointer
    }

    _Deque_iterator(_Size_type _Off, const _Container_base12* _Pdeque)
        : _Mybase(_Off, _Pdeque) { // construct with offset _Off in *_Pdeque
    }

    _NODISCARD reference operator*() const { // return designated object
        return (reference) * *(_Mybase*) this;
    }

    _NODISCARD pointer operator->() const { // return pointer to class object
        return pointer_traits<pointer>::pointer_to(**this);
    }

    _Deque_iterator& operator++() { // preincrement
        ++*(_Mybase*) this;
        return *this;
    }

    _Deque_iterator operator++(int) { // postincrement
        _Deque_iterator _Tmp = *this;
        ++*this;
        return _Tmp;
    }

    _Deque_iterator& operator--() { // predecrement
        --*(_Mybase*) this;
        return *this;
    }

    _Deque_iterator operator--(int) { // postdecrement
        _Deque_iterator _Tmp = *this;
        --*this;
        return _Tmp;
    }

    _Deque_iterator& operator+=(const difference_type _Off) { // increment by integer
        this->_Myoff += _Off;
        return *this;
    }

    _NODISCARD _Deque_iterator operator+(const difference_type _Off) const { // return this + integer
        _Deque_iterator _Tmp = *this;
        return _Tmp += _Off;
    }

    _Deque_iterator& operator-=(const difference_type _Off) { // decrement by integer
        return *this += -_Off;
    }

    _NODISCARD _Deque_iterator operator-(const difference_type _Off) const { // return this - integer
        _Deque_iterator _Tmp = *this;
        return _Tmp -= _Off;
    }

    _NODISCARD difference_type operator-(const _Mybase& _Right) const { // return difference of iterators
        return *(_Mybase*) this - _Right;
    }

    _NODISCARD reference operator[](const difference_type _Off) const { // subscript
        return *(*this + _Off);
    }

    using _Prevent_inheriting_unwrap = _Deque_iterator;

    _NODISCARD _Deque_unchecked_iterator<_Mydeque> _Unwrapped() const {
        return {this->_Myoff, this->_Getcont()};
    }
};

template <class _Mydeque>
_NODISCARD inline _Deque_iterator<_Mydeque> operator+(typename _Deque_iterator<_Mydeque>::difference_type _Off,
    _Deque_iterator<_Mydeque> _Next) { // add offset to iterator
    return _Next += _Off;
}

// deque TYPE WRAPPERS
template <class _Value_type, class _Size_type, class _Difference_type, class _Pointer, class _Const_pointer,
    class _Reference, class _Const_reference,
    class _Mapptr_type>
struct _Deque_iter_types { // wraps types needed by iterators
    using value_type      = _Value_type;
    using size_type       = _Size_type;
    using difference_type = _Difference_type;
    using pointer         = _Pointer;
    using const_pointer   = _Const_pointer;
    using _Mapptr         = _Mapptr_type;
};

template <class _Ty>
struct _Deque_simple_types : public _Simple_types<_Ty> { // wraps types needed by iterators
    using _Mapptr = _Ty**;
};

// CLASS TEMPLATE _Deque_val
template <class _Val_types>
class _Deque_val : public _Container_base12 { // base class for deque to hold data
public:
    using value_type      = typename _Val_types::value_type;
    using size_type       = typename _Val_types::size_type;
    using difference_type = typename _Val_types::difference_type;
    using pointer         = typename _Val_types::pointer;
    using const_pointer   = typename _Val_types::const_pointer;
    using reference       = value_type&;
    using const_reference = const value_type&;
    using _Mapptr         = typename _Val_types::_Mapptr;

    _Deque_val() : _Map(), _Mapsize(0), _Myoff(0), _Mysize(0) { // initialize values
    }

    size_type _Getblock(size_type _Off) const { // determine block from offset
                                                // NB: _Mapsize and _DEQUESIZ are guaranteed to be powers of 2
        return (_Off / _DEQUESIZ) & (_Mapsize - 1);
    }

    _Mapptr _Map; // pointer to array of pointers to blocks
    size_type _Mapsize; // size of map array, zero or 2^N
    size_type _Myoff; // offset of initial element
    size_type _Mysize; // current length of sequence
};

// CLASS TEMPLATE deque
template <class _Ty,
    class _Alloc = allocator<_Ty>>
class deque { // circular queue of pointers to blocks
private:
    friend _Tidy_guard<deque>;
    static_assert(!_ENFORCE_MATCHING_ALLOCATORS || is_same_v<_Ty, typename _Alloc::value_type>,
        _MISMATCHED_ALLOCATOR_MESSAGE("deque<T, Allocator>", "T"));

    using _Alty           = _Rebind_alloc_t<_Alloc, _Ty>;
    using _Alty_traits    = allocator_traits<_Alty>;
    using _Alpty          = _Rebind_alloc_t<_Alloc, typename _Alty_traits::pointer>;
    using _Alpty_traits   = allocator_traits<_Alpty>;
    using _Mapptr         = typename _Alpty_traits::pointer;
    using _Alproxy_ty     = _Rebind_alloc_t<_Alty, _Container_proxy>;
    using _Alproxy_traits = allocator_traits<_Alproxy_ty>;

    using _Scary_val = _Deque_val<conditional_t<_Is_simple_alloc_v<_Alty>, _Deque_simple_types<_Ty>,
        _Deque_iter_types<_Ty, typename _Alty_traits::size_type, typename _Alty_traits::difference_type,
            typename _Alty_traits::pointer, typename _Alty_traits::const_pointer, _Ty&, const _Ty&, _Mapptr>>>;

public:
    using allocator_type  = _Alloc;
    using value_type      = _Ty;
    using size_type       = typename _Alty_traits::size_type;
    using difference_type = typename _Alty_traits::difference_type;
    using pointer         = typename _Alty_traits::pointer;
    using const_pointer   = typename _Alty_traits::const_pointer;
    using reference       = _Ty&;
    using const_reference = const _Ty&;

    using iterator                  = _Deque_iterator<_Scary_val>;
    using const_iterator            = _Deque_const_iterator<_Scary_val>;
    using _Unchecked_iterator       = _Deque_unchecked_iterator<_Scary_val>;
    using _Unchecked_const_iterator = _Deque_unchecked_const_iterator<_Scary_val>;

    using reverse_iterator       = _STD reverse_iterator<iterator>;
    using const_reverse_iterator = _STD reverse_iterator<const_iterator>;
    enum { _EEN_DS = _DEQUESIZ }; // helper for expression evaluator

    deque() : _Mypair(_Zero_then_variadic_args_t()) { // construct empty deque
        _Get_data()._Alloc_proxy(static_cast<_Alproxy_ty>(_Getal()));
    }

    explicit deque(const _Alloc& _Al)
        : _Mypair(_One_then_variadic_args_t(), _Al) { // construct empty deque with allocator
        _Get_data()._Alloc_proxy(static_cast<_Alproxy_ty>(_Getal()));
    }

    explicit deque(_CRT_GUARDOVERFLOW size_type _Count, const _Alloc& _Al = _Alloc())
        : _Mypair(_One_then_variadic_args_t(), _Al) { // construct from _Count * _Ty(), optional allocator
        _Alproxy_ty _Alproxy(_Getal());
        _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data());
        resize(_Count);
        _Proxy._Release();
    }

    deque(_CRT_GUARDOVERFLOW size_type _Count, const _Ty& _Val)
        : _Mypair(_Zero_then_variadic_args_t()) { // construct from _Count * _Val
        _Alproxy_ty _Alproxy(_Getal());
        _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data());
        _Construct_n(_Count, _Val);
        _Proxy._Release();
    }

    deque(_CRT_GUARDOVERFLOW size_type _Count, const _Ty& _Val, const _Alloc& _Al)
        : _Mypair(_One_then_variadic_args_t(), _Al) { // construct from _Count * _Val with allocator
        _Alproxy_ty _Alproxy(_Getal());
        _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data());
        _Construct_n(_Count, _Val);
        _Proxy._Release();
    }

    deque(const deque& _Right)
        : _Mypair(_One_then_variadic_args_t(),
              _Alty_traits::select_on_container_copy_construction(_Right._Getal())) { // construct by copying _Right
        _Alproxy_ty _Alproxy(_Getal());
        _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data());
        _Construct(_Right._Unchecked_begin(), _Right._Unchecked_end());
        _Proxy._Release();
    }

    deque(const deque& _Right, const _Alloc& _Al)
        : _Mypair(_One_then_variadic_args_t(), _Al) { // construct by copying _Right
        _Alproxy_ty _Alproxy(_Getal());
        _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data());
        _Construct(_Right._Unchecked_begin(), _Right._Unchecked_end());
        _Proxy._Release();
    }

    template <class _Iter, class = enable_if_t<_Is_iterator_v<_Iter>>>
    deque(_Iter _First, _Iter _Last) : _Mypair(_Zero_then_variadic_args_t()) { // construct from [_First, _Last)
        _Alproxy_ty _Alproxy(_Getal());
        _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data());
        _Construct(_First, _Last);
        _Proxy._Release();
    }

    template <class _Iter, class = enable_if_t<_Is_iterator_v<_Iter>>>
    deque(_Iter _First, _Iter _Last, const _Alloc& _Al)
        : _Mypair(_One_then_variadic_args_t(), _Al) { // construct from [_First, _Last) with allocator
        _Alproxy_ty _Alproxy(_Getal());
        _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data());
        _Construct(_First, _Last);
        _Proxy._Release();
    }

private:
    template <class _Iter>
    void _Construct(_Iter _First, _Iter _Last) { // initialize from [_First, _Last), input iterators
        _Tidy_guard<deque> _Guard{this};
        for (; _First != _Last; ++_First) {
            emplace_back(*_First);
        }

        _Guard._Target = nullptr;
    }

    void _Construct_n(size_type _Count, const _Ty& _Val) { // construct from _Count * _Val
        _Tidy_guard<deque> _Guard{this};
        for (; 0 < _Count; --_Count) {
            _Push_back_internal(_Val);
        }

        _Guard._Target = nullptr;
    }

#define _PUSH_FRONT_BEGIN                                                                 \
    if (_Myoff() % _DEQUESIZ == 0 && _Mapsize() <= (_Mysize() + _DEQUESIZ) / _DEQUESIZ) { \
        _Growmap(1);                                                                      \
    }                                                                                     \
    _Myoff() &= _Mapsize() * _DEQUESIZ - 1;                                               \
    size_type _Newoff = _Myoff() != 0 ? _Myoff() : _Mapsize() * _DEQUESIZ;                \
    size_type _Block  = _Getblock(--_Newoff);                                             \
    if (_Map()[_Block] == pointer()) {                                                    \
        _Map()[_Block] = _Getal().allocate(_DEQUESIZ);                                    \
    }

#define _PUSH_FRONT_END \
    _Myoff() = _Newoff; \
    ++_Mysize()

#define _PUSH_BACK_BEGIN                                                                                \
    if ((_Myoff() + _Mysize()) % _DEQUESIZ == 0 && _Mapsize() <= (_Mysize() + _DEQUESIZ) / _DEQUESIZ) { \
        _Growmap(1);                                                                                    \
    }                                                                                                   \
    _Myoff() &= _Mapsize() * _DEQUESIZ - 1;                                                             \
    size_type _Newoff = _Myoff() + _Mysize();                                                           \
    size_type _Block  = _Getblock(_Newoff);                                                             \
    if (_Map()[_Block] == pointer()) {                                                                  \
        _Map()[_Block] = _Getal().allocate(_DEQUESIZ);                                                  \
    }

#define _PUSH_BACK_END ++_Mysize()

public:
    deque(deque&& _Right)
        : _Mypair(_One_then_variadic_args_t(), _STD move(_Right._Getal())) { // construct by moving _Right
        _Get_data()._Alloc_proxy(static_cast<_Alproxy_ty>(_Getal()));
        _Take_contents(_Right);
    }

    deque(deque&& _Right, const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t(), _Al) { // construct by moving _Right
        _Alproxy_ty _Alproxy(_Getal());
        if
            _CONSTEXPR_IF(!_Alty_traits::is_always_equal::value) {
                if (_Getal() != _Right._Getal()) {
                    _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data());
                    _Construct(_STD make_move_iterator(_Right._Unchecked_begin()),
                        _STD make_move_iterator(_Right._Unchecked_end()));
                    _Proxy._Release();
                    return;
                }
            }

        _Get_data()._Alloc_proxy(_Alproxy);
        _Take_contents(_Right);
    }

private:
    void _Move_assign(deque& _Right, _Equal_allocators) noexcept {
        _Tidy();
        _Pocma(_Getal(), _Right._Getal());
        _Take_contents(_Right);
    }

    void _Move_assign(deque& _Right, _Propagate_allocators) {
        if (_Getal() == _Right._Getal()) {
            _Move_assign(_Right, _Equal_allocators{});
        } else {
            _Alproxy_ty _Alproxy(_Getal());
            _Alproxy_ty _Alproxy_right(_Right._Getal());
            _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy_right, _Leave_proxy_unbound{});
            _Tidy();
            _Pocma(_Getal(), _Right._Getal());
            _Proxy._Bind(_Alproxy, _STD addressof(_Get_data()));
            _Take_contents(_Right);
        }
    }

    void _Move_assign(deque& _Right, _No_propagate_allocators) {
        if (_Getal() == _Right._Getal()) {
            _Move_assign(_Right, _Equal_allocators{});
        } else {
            assign(
                _STD make_move_iterator(_Right._Unchecked_begin()), _STD make_move_iterator(_Right._Unchecked_end()));
        }
    }

public:
    deque& operator=(deque&& _Right) _NOEXCEPT_COND(_Alty_traits::is_always_equal::value) {
        if (this != _STD addressof(_Right)) {
            _Move_assign(_Right, _Choose_pocma<_Alty>{});
        }

        return *this;
    }

private:
    void _Take_contents(deque& _Right) noexcept {
        // move from _Right, stealing its contents
        // pre: _Getal() == _Right._Getal()
        auto& _My_data    = _Get_data();
        auto& _Right_data = _Right._Get_data();
        _My_data._Swap_proxy_and_iterators(_Right_data);
        _My_data._Map     = _Right_data._Map;
        _My_data._Mapsize = _Right_data._Mapsize;
        _My_data._Myoff   = _Right_data._Myoff;
        _My_data._Mysize  = _Right_data._Mysize;

        _Right_data._Map     = nullptr;
        _Right_data._Mapsize = 0;
        _Right_data._Myoff   = 0;
        _Right_data._Mysize  = 0;
    }

public:
    void push_front(_Ty&& _Val) { // insert element at beginning
        _Orphan_all();
        _PUSH_FRONT_BEGIN;
        _Alty_traits::construct(_Getal(), _Unfancy(_Map()[_Block] + _Newoff % _DEQUESIZ), _STD move(_Val));
        _PUSH_FRONT_END;
    }

private:
    void _Push_back_internal(_Ty&& _Val) { // insert element at end
        _PUSH_BACK_BEGIN;
        _Alty_traits::construct(_Getal(), _Unfancy(_Map()[_Block] + _Newoff % _DEQUESIZ), _STD move(_Val));
        _PUSH_BACK_END;
    }

public:
    void push_back(_Ty&& _Val) { // insert element at end
        _Orphan_all();
        _Push_back_internal(_STD move(_Val));
    }

    iterator insert(const_iterator _Where, _Ty&& _Val) { // insert _Val at _Where
        return emplace(_Where, _STD move(_Val));
    }

    template <class... _Valty>
    decltype(auto) emplace_front(_Valty&&... _Val) { // insert element at beginning
        _Orphan_all();
        _PUSH_FRONT_BEGIN;
        _Alty_traits::construct(
            _Getal(), _Unfancy(_Map()[_Block] + _Newoff % _DEQUESIZ), _STD forward<_Valty>(_Val)...);
        _PUSH_FRONT_END;

#if _HAS_CXX17
        return front();
#endif // _HAS_CXX17
    }

    template <class... _Valty>
    decltype(auto) emplace_back(_Valty&&... _Val) { // insert element at end
        _Orphan_all();
        _PUSH_BACK_BEGIN;
        _Alty_traits::construct(
            _Getal(), _Unfancy(_Map()[_Block] + _Newoff % _DEQUESIZ), _STD forward<_Valty>(_Val)...);
        _PUSH_BACK_END;

#if _HAS_CXX17
        return back();
#endif // _HAS_CXX17
    }

    template <class... _Valty>
    iterator emplace(const_iterator _Where, _Valty&&... _Val) { // insert element at _Where
        const auto _Off = static_cast<size_type>(_Where - begin());

#if _ITERATOR_DEBUG_LEVEL == 2
        _STL_VERIFY(_Off <= _Mysize(), "deque emplace iterator outside range");
#endif // _ITERATOR_DEBUG_LEVEL == 2

        if (_Off <= _Mysize() / 2) { // closer to front, push to front then rotate
            emplace_front(_STD forward<_Valty>(_Val)...);
            _STD rotate(begin(), begin() + 1, begin() + static_cast<difference_type>(1 + _Off));
        } else { // closer to back, push to back then rotate
            emplace_back(_STD forward<_Valty>(_Val)...);
            _STD rotate(begin() + static_cast<difference_type>(_Off), end() - 1, end());
        }
        return begin() + static_cast<difference_type>(_Off);
    }

    deque(initializer_list<_Ty> _Ilist, const _Alloc& _Al = allocator_type())
        : _Mypair(_One_then_variadic_args_t(), _Al) { // construct from initializer_list
        _Alproxy_ty _Alproxy(_Getal());
        _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data());
        _Construct(_Ilist.begin(), _Ilist.end());
        _Proxy._Release();
    }

    deque& operator=(initializer_list<_Ty> _Ilist) { // assign initializer_list
        assign(_Ilist.begin(), _Ilist.end());
        return *this;
    }

    void assign(initializer_list<_Ty> _Ilist) { // assign initializer_list
        assign(_Ilist.begin(), _Ilist.end());
    }

    iterator insert(const_iterator _Where, initializer_list<_Ty> _Ilist) { // insert initializer_list
        return insert(_Where, _Ilist.begin(), _Ilist.end());
    }

    ~deque() noexcept { // destroy the deque
        _Tidy();
        _Alproxy_ty _Proxy_allocator(_Getal());
        _Delete_plain(_Proxy_allocator, _STD exchange(_Get_data()._Myproxy, nullptr));
    }

    void _Copy_assign(const deque& _Right, false_type) {
        _Pocca(_Getal(), _Right._Getal());
        assign(_Right._Unchecked_begin(), _Right._Unchecked_end());
    }

    void _Copy_assign(const deque& _Right, true_type) {
        if (_Getal() != _Right._Getal()) {
            _Tidy();
            _Get_data()._Reload_proxy(static_cast<_Alproxy_ty>(_Getal()), static_cast<_Alproxy_ty>(_Right._Getal()));
        }

        _Copy_assign(_Right, false_type{});
    }

    deque& operator=(const deque& _Right) { // assign _Right
        if (this != _STD addressof(_Right)) { // different, assign it
            _Copy_assign(_Right, _Choose_pocca<_Alty>{});
        }

        return *this;
    }

    _NODISCARD iterator begin() noexcept { // return iterator for beginning of mutable sequence
        return iterator(_Myoff(), _STD addressof(_Get_data()));
    }

    _NODISCARD const_iterator begin() const noexcept { // return iterator for beginning of nonmutable sequence
        return const_iterator(_Myoff(), _STD addressof(_Get_data()));
    }

    _NODISCARD iterator end() noexcept { // return iterator for end of mutable sequence
        return iterator(_Myoff() + _Mysize(), _STD addressof(_Get_data()));
    }

    _NODISCARD const_iterator end() const noexcept { // return iterator for end of nonmutable sequence
        return const_iterator(_Myoff() + _Mysize(), _STD addressof(_Get_data()));
    }

    _Unchecked_iterator _Unchecked_begin() noexcept { // return unchecked iterator for beginning of mutable sequence
        return _Unchecked_iterator(_Myoff(), _STD addressof(_Get_data()));
    }

    _Unchecked_const_iterator _Unchecked_begin() const
        noexcept { // return unchecked iterator for beginning of nonmutable sequence
        return _Unchecked_const_iterator(_Myoff(), _STD addressof(_Get_data()));
    }

    _Unchecked_iterator _Unchecked_end() noexcept { // return unchecked iterator for end of mutable sequence
        return _Unchecked_iterator(_Myoff() + _Mysize(), _STD addressof(_Get_data()));
    }

    _Unchecked_const_iterator _Unchecked_end() const
        noexcept { // return unchecked iterator for end of nonmutable sequence
        return _Unchecked_const_iterator(_Myoff() + _Mysize(), _STD addressof(_Get_data()));
    }

    iterator _Make_iter(const_iterator _Where) const { // make iterator from const_iterator
        return iterator(_Where._Myoff, _STD addressof(_Get_data()));
    }

    _NODISCARD reverse_iterator rbegin() noexcept { // return iterator for beginning of reversed mutable sequence
        return reverse_iterator(end());
    }

    _NODISCARD const_reverse_iterator rbegin() const
        noexcept { // return iterator for beginning of reversed nonmutable sequence
        return const_reverse_iterator(end());
    }

    _NODISCARD reverse_iterator rend() noexcept { // return iterator for end of reversed mutable sequence
        return reverse_iterator(begin());
    }

    _NODISCARD const_reverse_iterator rend() const noexcept { // return iterator for end of reversed nonmutable sequence
        return const_reverse_iterator(begin());
    }

    _NODISCARD const_iterator cbegin() const noexcept { // return iterator for beginning of nonmutable sequence
        return begin();
    }

    _NODISCARD const_iterator cend() const noexcept { // return iterator for end of nonmutable sequence
        return end();
    }

    _NODISCARD const_reverse_iterator crbegin() const
        noexcept { // return iterator for beginning of reversed nonmutable sequence
        return rbegin();
    }

    _NODISCARD const_reverse_iterator crend() const
        noexcept { // return iterator for end of reversed nonmutable sequence
        return rend();
    }

    void shrink_to_fit() { // reduce capacity
        size_type _Oldcapacity = _DEQUESIZ * _Mapsize();
        size_type _Newcapacity = _Oldcapacity / 2;

        if (_Newcapacity < _DEQUESIZ * _DEQUEMAPSIZ)
            _Newcapacity = _DEQUESIZ * _DEQUEMAPSIZ;

        if ((empty() && 0 < _Mapsize())
            || (!empty() && size() <= _Newcapacity && _Newcapacity < _Oldcapacity)) { // worth shrinking, do it
            deque _Tmp(_STD make_move_iterator(begin()), _STD make_move_iterator(end()));
            swap(_Tmp);
        }
    }

    void resize(_CRT_GUARDOVERFLOW size_type _Newsize) { // determine new length, padding as needed
        while (_Mysize() < _Newsize) {
            emplace_back();
        }

        while (_Newsize < _Mysize()) {
            pop_back();
        }
    }

    void resize(_CRT_GUARDOVERFLOW size_type _Newsize,
        const _Ty& _Val) { // determine new length, padding with _Val elements as needed
        _Orphan_all();
        while (_Mysize() < _Newsize) {
            _Push_back_internal(_Val);
        }

        while (_Newsize < _Mysize()) {
            pop_back();
        }
    }

    _NODISCARD size_type size() const noexcept { // return length of sequence
        return _Mysize();
    }

    _NODISCARD size_type max_size() const noexcept { // return maximum possible length of sequence
        return _Alty_traits::max_size(_Getal());
    }

    _NODISCARD bool empty() const noexcept { // test if sequence is empty
        return _Mysize() == 0;
    }

    _NODISCARD allocator_type get_allocator() const noexcept { // return allocator object for values
        return static_cast<allocator_type>(_Getal());
    }

    _NODISCARD const_reference at(size_type _Pos) const { // subscript nonmutable sequence with checking
        if (_Mysize() <= _Pos)
            _Xran();
        return *(begin() + static_cast<difference_type>(_Pos));
    }

    _NODISCARD reference at(size_type _Pos) { // subscript mutable sequence with checking
        if (_Mysize() <= _Pos) {
            _Xran();
        }

        return *(begin() + static_cast<difference_type>(_Pos));
    }

    _NODISCARD const_reference operator[](size_type _Pos) const { // subscript nonmutable sequence
#if _ITERATOR_DEBUG_LEVEL == 2
        _STL_VERIFY(_Pos < _Mysize(), "deque subscript out of range");
#endif // _ITERATOR_DEBUG_LEVEL == 2

        return *(begin() + static_cast<difference_type>(_Pos));
    }

    _NODISCARD reference operator[](size_type _Pos) { // subscript mutable sequence
#if _ITERATOR_DEBUG_LEVEL == 2
        _STL_VERIFY(_Pos < _Mysize(), "deque subscript out of range");
#endif // _ITERATOR_DEBUG_LEVEL == 2

        return *(begin() + static_cast<difference_type>(_Pos));
    }

    _NODISCARD reference front() { // return first element of mutable sequence
        return *begin();
    }

    _NODISCARD const_reference front() const { // return first element of nonmutable sequence
        return *begin();
    }

    _NODISCARD reference back() { // return last element of mutable sequence
        return *(end() - 1);
    }

    _NODISCARD const_reference back() const { // return last element of nonmutable sequence
        return *(end() - 1);
    }

    void push_front(const _Ty& _Val) { // insert element at beginning
        _Orphan_all();
        _PUSH_FRONT_BEGIN;
        _Alty_traits::construct(_Getal(), _Unfancy(_Map()[_Block] + _Newoff % _DEQUESIZ), _Val);
        _PUSH_FRONT_END;
    }

    void pop_front() { // erase element at beginning
#if _ITERATOR_DEBUG_LEVEL == 2
        if (empty()) {
            _STL_REPORT_ERROR("deque empty before pop");
        } else { // something to erase, do it
            _Orphan_off(_Myoff());
            size_type _Block = _Getblock(_Myoff());
            _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Myoff() % _DEQUESIZ));
            if (--_Mysize() == 0) {
                _Myoff() = 0;
            } else {
                ++_Myoff();
            }
        }

#else // _ITERATOR_DEBUG_LEVEL == 2
        size_type _Block = _Getblock(_Myoff());
        _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Myoff() % _DEQUESIZ));
        if (--_Mysize() == 0) {
            _Myoff() = 0;
        } else {
            ++_Myoff();
        }
#endif // _ITERATOR_DEBUG_LEVEL == 2
    }

private:
    void _Push_back_internal(const _Ty& _Val) {
        _PUSH_BACK_BEGIN;
        _Alty_traits::construct(_Getal(), _Unfancy(_Map()[_Block] + _Newoff % _DEQUESIZ), _Val);
        _PUSH_BACK_END;
    }

public:
    void push_back(const _Ty& _Val) { // insert element at end
        _Orphan_all();
        _Push_back_internal(_Val);
    }

    void pop_back() { // erase element at end
#if _ITERATOR_DEBUG_LEVEL == 2
        if (empty()) {
            _STL_REPORT_ERROR("deque empty before pop");
        } else { // something to erase, do it
            size_type _Newoff = _Myoff() + _Mysize() - 1;
            _Orphan_off(_Newoff);
            size_type _Block = _Getblock(_Newoff);
            _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Newoff % _DEQUESIZ));
            if (--_Mysize() == 0) {
                _Myoff() = 0;
            }
        }

#else // _ITERATOR_DEBUG_LEVEL == 2
        size_type _Newoff = _Myoff() + _Mysize() - 1;
        size_type _Block  = _Getblock(_Newoff);
        _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Newoff % _DEQUESIZ));
        if (--_Mysize() == 0) {
            _Myoff() = 0;
        }
#endif // _ITERATOR_DEBUG_LEVEL == 2
    }

    template <class _Iter, class = enable_if_t<_Is_iterator_v<_Iter>>>
    void assign(_Iter _First, _Iter _Last) { // assign [_First, _Last), input iterators
        _Orphan_all();
        _Adl_verify_range(_First, _Last);
        auto _UFirst       = _Get_unwrapped(_First);
        const auto _ULast  = _Get_unwrapped(_Last);
        auto _Myfirst      = _Unchecked_begin();
        const auto _Mylast = _Unchecked_end();
        for (; _UFirst != _ULast; ++_UFirst) { // try to assign over an element in the container
            if (_Myfirst == _Mylast) { // container wasn't big enough, insert what's left at end
                do {
                    emplace_back(*_UFirst);
                    ++_UFirst;
                } while (_UFirst != _ULast);
                return;
            }

            *_Myfirst = *_UFirst;
            ++_Myfirst;
        }

        _Erase_last_n(static_cast<size_type>(_Mylast - _Myfirst));
    }

    void assign(_CRT_GUARDOVERFLOW size_type _Count, const _Ty& _Val) { // assign _Count * _Val
        _Orphan_all();
        auto _Myfirst       = _Unchecked_begin();
        const auto _Oldsize = _Mysize();
        auto _Assign_count  = _Min_value(_Count, _Oldsize);
        for (; 0 < _Assign_count; --_Assign_count) {
            *_Myfirst = _Val;
            ++_Myfirst;
        }

        const auto _Shrink_by = _Oldsize - _Assign_count;
        auto _Extend_by       = _Count - _Assign_count;
        _Erase_last_n(_Shrink_by);
        for (; 0 < _Extend_by; --_Extend_by) {
            _Push_back_internal(_Val);
        }
    }

    iterator insert(const_iterator _Where,
        const _Ty& _Val) { // insert _Val at _Where
        size_type _Off = static_cast<size_type>(_Where - begin());

#if _ITERATOR_DEBUG_LEVEL == 2
        _STL_VERIFY(_Off <= _Mysize(), "deque insert iterator outside range");
#endif // _ITERATOR_DEBUG_LEVEL == 2

        if (_Off <= _Mysize() / 2) { // closer to front, push to front then copy
            push_front(_Val);
            _STD rotate(begin(), begin() + 1, begin() + static_cast<difference_type>(1 + _Off));
        } else { // closer to back, push to back then copy
            push_back(_Val);
            _STD rotate(begin() + static_cast<difference_type>(_Off), end() - 1, end());
        }

        return begin() + static_cast<difference_type>(_Off);
    }

    iterator insert(const_iterator _Where, _CRT_GUARDOVERFLOW size_type _Count,
        const _Ty& _Val) { // insert _Count * _Val at _Where
        size_type _Off = static_cast<size_type>(_Where - begin());
        _Insert_n(_Where, _Count, _Val);
        return begin() + static_cast<difference_type>(_Off);
    }

    template <class _Iter, class = enable_if_t<_Is_iterator_v<_Iter>>>
    iterator insert(
        const_iterator _Where, _Iter _First, _Iter _Last) { // insert [_First, _Last) at _Where, input iterators
        size_type _Off = static_cast<size_type>(_Where - begin());

#if _ITERATOR_DEBUG_LEVEL == 2
        _STL_VERIFY(_Mysize() >= _Off, "deque insert iterator outside range");
#endif // _ITERATOR_DEBUG_LEVEL == 2

        _Adl_verify_range(_First, _Last);
        auto _UFirst      = _Get_unwrapped(_First);
        const auto _ULast = _Get_unwrapped(_Last);

        size_type _Oldsize = _Mysize();

        if (_UFirst != _ULast) {
            if (_Off <= _Mysize() / 2) { // closer to front, push to front then rotate
                _TRY_BEGIN
                for (; _UFirst != _ULast; ++_UFirst) {
                    push_front(*_UFirst); // prepend flipped
                }

                _CATCH_ALL
                while (_Oldsize < _Mysize()) {
                    pop_front(); // restore old size, at least
                }

                _RERAISE;
                _CATCH_END

                size_type _Num = _Mysize() - _Oldsize;
                _STD reverse(begin(), begin() + static_cast<difference_type>(_Num)); // flip new stuff in place
                _STD rotate(begin(), begin() + static_cast<difference_type>(_Num),
                    begin() + static_cast<difference_type>(_Num + _Off));
            } else { // closer to back
                _TRY_BEGIN
                _Orphan_all();
                for (; _UFirst != _ULast; ++_UFirst) {
                    _Push_back_internal(*_UFirst);
                }

                _CATCH_ALL
                while (_Oldsize < _Mysize()) {
                    pop_back(); // restore old size, at least
                }

                _RERAISE;
                _CATCH_END

                _STD rotate(begin() + static_cast<difference_type>(_Off),
                    begin() + static_cast<difference_type>(_Oldsize), end());
            }
        }

        return begin() + static_cast<difference_type>(_Off);
    }

    iterator erase(const_iterator _Where) { // erase element at _Where
        return erase(_Where, _Where + 1);
    }

    iterator erase(const_iterator _First_arg, const_iterator _Last_arg) { // erase [_First, _Last)
        iterator _First = _Make_iter(_First_arg);
        iterator _Last  = _Make_iter(_Last_arg);

#if _ITERATOR_DEBUG_LEVEL == 2
        _STL_VERIFY(_First <= _Last && begin() <= _First && _Last <= end(), "deque erase iterator outside range");
        _Adl_verify_range(_First, _Last);

        auto _Off   = static_cast<size_type>(_First - begin());
        auto _Count = static_cast<size_type>(_Last - _First);
        bool _Moved = 0 < _Off && _Off + _Count < _Mysize();

#else // _ITERATOR_DEBUG_LEVEL == 2
        auto _Off   = static_cast<size_type>(_First - begin());
        auto _Count = static_cast<size_type>(_Last - _First);
#endif // _ITERATOR_DEBUG_LEVEL == 2

        if (_Off < static_cast<size_type>(end() - _Last)) { // closer to front
            _STD move_backward(begin(), _First, _Last); // copy over hole
            for (; 0 < _Count; --_Count) {
                pop_front(); // pop copied elements
            }
        } else { // closer to back
            _STD move(_Last, end(), _First); // copy over hole
            for (; 0 < _Count; --_Count) {
                pop_back(); // pop copied elements
            }
        }

#if _ITERATOR_DEBUG_LEVEL == 2
        if (_Moved) {
            _Orphan_all();
        }
#endif // _ITERATOR_DEBUG_LEVEL == 2

        return begin() + static_cast<difference_type>(_Off);
    }

private:
    void _Erase_last_n(size_type _Count) noexcept {
        for (; 0 < _Count; --_Count) {
            pop_back();
        }
    }

public:
    void clear() noexcept { // erase all
        _Tidy();
    }

    void swap(deque& _Right) noexcept { // strengthened
        // exchange contents with _Right
        if (this != _STD addressof(_Right)) { // (maybe) swap allocators, swap control information
            _Pocs(_Getal(), _Right._Getal());
            auto& _My_data    = _Get_data();
            auto& _Right_data = _Right._Get_data();
            _My_data._Swap_proxy_and_iterators(_Right_data);
            _Swap_adl(_My_data._Map, _Right_data._Map);
            _STD swap(_My_data._Mapsize, _Right_data._Mapsize);
            _STD swap(_My_data._Myoff, _Right_data._Myoff);
            _STD swap(_My_data._Mysize, _Right_data._Mysize);
        }
    }

private:
    void _Insert_n(const_iterator _Where, size_type _Count, const _Ty& _Val) { // insert _Count * _Val at _Where
        iterator _Mid;
        size_type _Num;
        size_type _Off     = static_cast<size_type>(_Where - begin());
        size_type _Oldsize = _Mysize();
        size_type _Rem     = _Oldsize - _Off;

#if _ITERATOR_DEBUG_LEVEL == 2
        _STL_VERIFY(_Off <= _Oldsize, "deque insert iterator outside range");
#endif // _ITERATOR_DEBUG_LEVEL == 2

        if (_Off < _Rem) { // closer to front
            _TRY_BEGIN
            if (_Off < _Count) { // insert longer than prefix
                for (_Num = _Count - _Off; 0 < _Num; --_Num) {
                    push_front(_Val); // push excess values
                }
                for (_Num = _Off; 0 < _Num; --_Num) {
                    push_front(begin()[static_cast<difference_type>(_Count - 1)]); // push prefix
                }

                _Mid = begin() + static_cast<difference_type>(_Count);
                _STD fill(_Mid, _Mid + static_cast<difference_type>(_Off), _Val); // fill in rest of values
            } else { // insert not longer than prefix
                for (_Num = _Count; 0 < _Num; --_Num) {
                    push_front(begin()[static_cast<difference_type>(_Count - 1)]); // push part of prefix
                }

                _Mid     = begin() + static_cast<difference_type>(_Count);
                _Ty _Tmp = _Val; // in case _Val is in sequence
                _STD move(_Mid + static_cast<difference_type>(_Count), _Mid + static_cast<difference_type>(_Off),
                    _Mid); // copy rest of prefix
                _STD fill(begin() + static_cast<difference_type>(_Off), _Mid + static_cast<difference_type>(_Off),
                    _Tmp); // fill in values
            }
            _CATCH_ALL
            while (_Oldsize < _Mysize()) {
                pop_front(); // restore old size, at least
            }

            _RERAISE;
            _CATCH_END
        } else { // closer to back
            _TRY_BEGIN
            if (_Rem < _Count) { // insert longer than suffix
                _Orphan_all();
                for (_Num = _Count - _Rem; 0 < _Num; --_Num) {
                    _Push_back_internal(_Val); // push excess values
                }
                for (_Num = 0; _Num < _Rem; ++_Num) {
                    _Push_back_internal(begin()[static_cast<difference_type>(_Off + _Num)]); // push suffix
                }

                _Mid = begin() + static_cast<difference_type>(_Off);
                _STD fill(_Mid, _Mid + static_cast<difference_type>(_Rem), _Val); // fill in rest of values
            } else { // insert not longer than prefix
                for (_Num = 0; _Num < _Count; ++_Num) {
                    _Push_back_internal(
                        begin()[static_cast<difference_type>(_Off + _Rem - _Count + _Num)]); // push part of prefix
                }

                _Mid     = begin() + static_cast<difference_type>(_Off);
                _Ty _Tmp = _Val; // in case _Val is in sequence
                _STD move_backward(_Mid, _Mid + static_cast<difference_type>(_Rem - _Count),
                    _Mid + static_cast<difference_type>(_Rem)); // copy rest of prefix
                _STD fill(_Mid, _Mid + static_cast<difference_type>(_Count), _Tmp); // fill in values
            }
            _CATCH_ALL
            _Erase_last_n(_Mysize() - _Oldsize);
            _RERAISE;
            _CATCH_END
        }
    }

    [[noreturn]] void _Xlen() const { // report a length_error
        _Xlength_error("deque<T> too long");
    }

    [[noreturn]] void _Xran() const { // report an out_of_range error
        _Xout_of_range("invalid deque<T> subscript");
    }

    void _Growmap(size_type _Count) { // grow map by at least _Count pointers, _Mapsize() a power of 2
        static_assert(1 < _DEQUEMAPSIZ, "The _Xlen() test should always be performed.");

        _Alpty _Almap(_Getal());
        size_type _Newsize = 0 < _Mapsize() ? _Mapsize() : 1;
        while (
            _Newsize - _Mapsize() < _Count || _Newsize < _DEQUEMAPSIZ) { // scale _Newsize to 2^N >= _Mapsize() + _Count
            if (max_size() / _DEQUESIZ - _Newsize < _Newsize) {
                _Xlen(); // result too long
            }

            _Newsize *= 2;
        }
        _Count = _Newsize - _Mapsize();

        size_type _Myboff = _Myoff() / _DEQUESIZ;
        _Mapptr _Newmap   = _Almap.allocate(_Mapsize() + _Count);
        _Mapptr _Myptr    = _Newmap + _Myboff;

        _Myptr = _Uninitialized_copy(_Map() + _Myboff, _Map() + _Mapsize(), _Myptr, _Almap); // copy initial to end
        if (_Myboff <= _Count) { // increment greater than offset of initial block
            _Myptr = _Uninitialized_copy(_Map(), _Map() + _Myboff, _Myptr, _Almap); // copy rest of old
            _Uninitialized_value_construct_n(_Myptr, _Count - _Myboff,
                _Almap); // clear suffix of new
            _Uninitialized_value_construct_n(_Newmap, _Myboff,
                _Almap); // clear prefix of new
        } else { // increment not greater than offset of initial block
            _Uninitialized_copy(_Map(), _Map() + _Count, _Myptr, _Almap); // copy more old
            _Myptr = _Uninitialized_copy(_Map() + _Count, _Map() + _Myboff, _Newmap, _Almap); // copy rest of old
            _Uninitialized_value_construct_n(_Myptr, _Count,
                _Almap); // clear rest to initial block
        }

        _Destroy_range(_Map() + _Myboff, _Map() + _Mapsize(), _Almap);
        if (_Map() != _Mapptr()) {
            _Almap.deallocate(_Map(), _Mapsize()); // free storage for old
        }

        _Map() = _Newmap; // point at new
        _Mapsize() += _Count;
    }

    void _Tidy() noexcept { // free all storage
        _Alpty _Almap(_Getal());
        while (!empty()) {
            pop_back();
        }

        for (size_type _Block = _Mapsize(); 0 < _Block;) { // free storage for a block and destroy pointer
            if (_Map()[--_Block] != pointer()) { // free block and destroy its pointer
                _Getal().deallocate(_Map()[_Block], _DEQUESIZ);
                _Alpty_traits::destroy(_Almap, _STD addressof(_Map()[_Block]));
            }
        }

        if (_Map() != _Mapptr()) {
            _Almap.deallocate(_Map(), _Mapsize()); // free storage for map
        }

        _Mapsize() = 0;
        _Map()     = _Mapptr();
    }

#if _ITERATOR_DEBUG_LEVEL == 2
    void _Orphan_off(size_type _Offlo) const { // orphan iterators with specified offset(s)
        size_type _Offhigh = _Myoff() + _Mysize() <= _Offlo + 1 ? (size_type)(-1) : _Offlo;
        if (_Offlo == _Myoff()) {
            _Offlo = 0;
        }

        _Lockit _Lock(_LOCK_DEBUG);
        _Iterator_base12** _Pnext = &_Get_data()._Myproxy->_Myfirstiter;
        while (*_Pnext != nullptr) {
            const auto _Pnextoff = static_cast<const_iterator&>(**_Pnext)._Myoff;
            if (_Pnextoff < _Offlo || _Offhigh < _Pnextoff) {
                _Pnext = &(*_Pnext)->_Mynextiter;
            } else { // orphan the iterator
                (*_Pnext)->_Myproxy = nullptr;
                *_Pnext             = (*_Pnext)->_Mynextiter;
            }
        }
    }
#endif // _ITERATOR_DEBUG_LEVEL == 2

    size_type _Getblock(size_type _Off) const { // determine block from offset
        return _Get_data()._Getblock(_Off);
    }

    void _Orphan_all() { // orphan all iterators
        _Get_data()._Orphan_all();
    }

    _Alty& _Getal() noexcept { // return reference to allocator
        return _Mypair._Get_first();
    }

    const _Alty& _Getal() const noexcept { // return const reference to allocator
        return _Mypair._Get_first();
    }

    _Scary_val& _Get_data() noexcept { // return reference to _Scary_val
        return _Mypair._Myval2;
    }

    const _Scary_val& _Get_data() const noexcept { // return const reference to _Scary_val
        return _Mypair._Myval2;
    }

    _Mapptr& _Map() noexcept { // return reference to _Map
        return _Get_data()._Map;
    }

    const _Mapptr& _Map() const noexcept { // return const reference to _Map
        return _Get_data()._Map;
    }

    size_type& _Mapsize() noexcept { // return reference to _Mapsize
        return _Get_data()._Mapsize;
    }

    const size_type& _Mapsize() const noexcept { // return const reference to _Mapsize
        return _Get_data()._Mapsize;
    }

    size_type& _Myoff() noexcept { // return reference to _Myoff
        return _Get_data()._Myoff;
    }

    const size_type& _Myoff() const noexcept { // return const reference to _Myoff
        return _Get_data()._Myoff;
    }

    size_type& _Mysize() noexcept { // return reference to _Mysize
        return _Get_data()._Mysize;
    }

    const size_type& _Mysize() const noexcept { // return const reference to _Mysize
        return _Get_data()._Mysize;
    }

    _Compressed_pair<_Alty, _Scary_val> _Mypair;
};

#if _HAS_CXX17
template <class _Iter, class _Alloc = allocator<_Iter_value_t<_Iter>>,
    enable_if_t<conjunction_v<_Is_iterator<_Iter>, _Is_allocator<_Alloc>>, int> = 0>
deque(_Iter, _Iter, _Alloc = _Alloc())->deque<_Iter_value_t<_Iter>, _Alloc>;
#endif // _HAS_CXX17

template <class _Ty, class _Alloc>
inline void swap(deque<_Ty, _Alloc>& _Left, deque<_Ty, _Alloc>& _Right) noexcept { // strengthened
    // swap _Left and _Right deques
    _Left.swap(_Right);
}

template <class _Ty, class _Alloc>
_NODISCARD inline bool operator==(
    const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) { // test for deque equality
    return _Left.size() == _Right.size()
           && _STD equal(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin());
}

template <class _Ty, class _Alloc>
_NODISCARD inline bool operator!=(
    const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) { // test for deque inequality
    return !(_Left == _Right);
}

template <class _Ty, class _Alloc>
_NODISCARD inline bool operator<(
    const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) { // test if _Left < _Right for deques
    return _STD lexicographical_compare(
        _Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin(), _Right._Unchecked_end());
}

template <class _Ty, class _Alloc>
_NODISCARD inline bool operator<=(
    const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) { // test if _Left <= _Right for deques
    return !(_Right < _Left);
}

template <class _Ty, class _Alloc>
_NODISCARD inline bool operator>(
    const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) { // test if _Left > _Right for deques
    return _Right < _Left;
}

template <class _Ty, class _Alloc>
_NODISCARD inline bool operator>=(
    const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) { // test if _Left >= _Right for deques
    return !(_Left < _Right);
}

#if _HAS_CXX17
namespace pmr {
    template <class _Ty>
    using deque = _STD deque<_Ty, polymorphic_allocator<_Ty>>;
} // namespace pmr
#endif // _HAS_CXX17
_STD_END

#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
#pragma pack(pop)
#endif // RC_INVOKED
#endif // _DEQUE_

/*
 * Copyright (c) by P.J. Plauger. All rights reserved.
 * Consult your license regarding permissions and restrictions.
V6.50:0009 */
